<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            border: 3px dashed #ccc;
            padding: 20px;
        }
    </style>
    <script src="../assets/js/vue.js"></script>
</head>
<body>
    <!-- 
        事件总线：通过事件的方法完成回调函数的执行，实现数据传递操作；而事件本身被一个统一的管理器进行管理
            1、如何定义一个可以被vue项目中任意vue实例访问的事件管理对象
            2、事件总线如何保持响应式的数据功能
        口诀：提供数据调用方法，接收数据定义方法
        注意事项：方法定义要早于方法触发
     -->
    <div id="app" class="box">
        <p>父组件</p>
        <comp-a></comp-a>
        <br>
        <comp-b></comp-b>
    </div>

    <script type="text/x-template" id="CompA">
        <div class="box">
            <p>子组件A</p>
            <p>tempMsg : {{ tempMsg }}</p>
            <input type="button" value="绑定事件" @click="bindMsgEvent()">
            <hr>
            <p>tempInfo:{{ tempInfo }}</p>
            <input type="button" value="绑定事件" @click="bindInfoEvent()">
        </div>
    </script>

    <script type="text/x-template" id="CompB">
        <div class="box">
            <p>子组件B</p>
            <p>msg:{{ msg }}</p>
            <input type="button" value="触发事件" @click="emitMsgEvent()">
            <hr>
            <p>info:{{ info }}</p>
            <input type="button" value="触发事件" @click="emitInfoEvent()">
        </div>
    </script>

    <script>

        // 事件总线的基础原理
        let events = {}
        // 符合规范的事件总线
        // + `vm.$on(eventName,callback) `: 在实例的自定义事件仓库`$listeners` 中装载自定义事件
        // + `vm.$once(eventName,callback) `: 在实例的自定义事件仓库`$listeners` 中装载一次性自定义事件
        // + `vm.$off(eventName) `: 在实例的自定义事件仓库`$listeners` 中卸载自定义事件
        // let eventBus = new Vue();
        // 通过实例属性 vm.$root 替换 eventBus;
        // `vm.$root` : 该属性提供在任意组件中可直接获取 Root组件(`new Vue()`)

        Vue.component("CompA",{
            template:"#CompA",
            data() {
                return {
                    tempMsg:"",
                    tempInfo:""
                }
            },
            methods: {
                bindMsgEvent:function(){
                    events.updateMsg = (nv)=>{
                        console.log("CompA=bindMsgEvent=形参值:",nv,this)
                        this.tempMsg = nv;
                    }
                },
                // bindInfoEvent(){
                //     console.log(this.$root);
                //     if(!eventBus._events.updateInfo){
                //         eventBus.$on("updateInfo",(nv)=>{
                //             console.log("CompA-bindInfoEvent-updateInfo事件:",nv)
                //             this.tempInfo = nv;
                //         })
                //     }
                // }
                bindInfoEvent(){
                    console.log(this.$root);
                    if(!this.$root._events.updateInfo){
                        this.$root.$on("updateInfo",(nv)=>{
                            console.log("CompA-bindInfoEvent-updateInfo事件:",nv)
                            this.tempInfo = nv;
                        })
                    }
                }
            },
        })

        Vue.component("CompB",{
            template:"#CompB",
            data() {
                return {
                    msg:"CompB-msg数据",
                    info:"CompB-info数据"
                }
            },
            methods:{
                emitMsgEvent(){
                    if( typeof(events.updateMsg)=="function"){
                        events.updateMsg(this.msg)
                    }
                },
                // emitInfoEvent(){
                //     console.log(this.$root)
                //     eventBus.$emit("updateInfo",this.info)
                // }
                emitInfoEvent(){
                    console.log(this.$root)
                    this.$root.$emit("updateInfo",this.info)
                }
            }
        })

        new Vue({
            el:"#app"
        })
    </script>
</body>
</html>